package main

import (
	"encoding/json"
	"fmt"
	"reflect"
)

// 例1 不使用反射时。所有结构体成员必须是大写开头，如小写开头则被认为是私有成员。
// 尽量用这种方式，大型结构体逐一反射真的很麻烦。
// Tips: 不使用反射时也是可以使用tag的！

type insidest struct {
	VarMapStrStr string
}

type demost struct {
	ValI          int
	ValF32        float32
	ValF64        float64
	ValBool       bool
	ValString     string
	ValListI      []int
	ValListF32    []float32 `json:"afl"` //这里序列化后Json中的key就变成了afl，而不是变量名ValListF32
	VarListF64    []float64
	VarListBool   []bool
	VarListString []string
	VarMapStrStr  map[string]string
	VarInside     insidest
}

func test1() {
	fmt.Println("例1：从无tag的struct序列化和反序列化json")
	// 序列化：从结构体struct生成JSON
	dmJson := &demost{
		1,
		2.1,
		3.1,
		true,
		"a string",
		[]int{1, 2, 3, 4, 5},
		[]float32{2.0, 3.1, 4.2, 5.3, 6.4},
		[]float64{5.1, 6.2},
		[]bool{true, false, true, false},
		[]string{"string1", "string2"},
		map[string]string{"key1": "value1", "key2": "value2"},
		insidest{"ivalue1"}}

	fmt.Println("结构体的值:", dmJson)
	bytes, err := json.Marshal(dmJson)
	if err != nil {
		fmt.Println("序列化JSON发生错误:", err.Error())
	} else {
		fmt.Println("序列化为字符串的结果：", string(bytes))
	}
	// 反序列化： 从JSON字符串为结构体赋值。
	dmJson2 := &demost{}
	json.Unmarshal(bytes, dmJson2)
	fmt.Println("反序列化后:", dmJson2)
}

// Tips: 下面结构体中的变量都是以小写字符开头，它们只能通过反射获取。
type taginsidest struct {
	varMapStrStr string `json:"VarMapStrStr"`
}

type tagdemost struct {
	valI          int               `json:"ValI"`
	valF32        float32           `json:"ValF32"`
	valF64        float64           `json:"ValF64"`
	valBool       bool              `json:"ValBool"`
	valString     string            `json:"ValString"`
	valListI      []int             `json:"ValListI"`
	valListF32    []float32         `json:"ValListF32"`
	varListF64    []float64         `json:"VarListF64"`
	varListBool   []bool            `json:"VarListBool"`
	varListString []string          `json:"VarListString"`
	varMapStrStr  map[string]string `json:"VarMapStrStr"`
	varInside     taginsidest       `json:"VarInside"`
}

func test2() {
	fmt.Println("例2：从带tag的struct序列化和反序列化json")
	// 序列化：从结构体struct生成JSON
	dmJson := &tagdemost{
		1,
		2.1,
		3.1,
		true,
		"a string",
		[]int{1, 2, 3, 4, 5},
		[]float32{2.0, 3.1, 4.2, 5.3, 6.4},
		[]float64{5.1, 6.2},
		[]bool{true, false, true, false},
		[]string{"string1", "string2"},
		map[string]string{"key1": "value1", "key2": "value2"},
		taginsidest{"ivalue1"}}

	fmt.Println("结构体的值:", dmJson)

	var to reflect.Type = reflect.TypeOf(dmJson)
	to = to.Elem()
	vo := reflect.ValueOf(dmJson)
	vo = vo.Elem()

	fmt.Println("TypeOf:", to, "NumberFiled:", to.NumField())
	mm := make(map[string]interface{}, 0)
	//mm["123"] = "456"
	//fmt.Println(mm)

	for i := 0; i < to.NumField(); i++ {
		fn := to.Field(i).Name
		ft := to.Field(i).Type
		ftt := to.Field(i).Tag
		fv := vo.Field(i)
		fmt.Println(fn, ft, ftt, ",value:", fv)
		if ft.String() == "int" {
			//fmt.Println("    Got int value, tag", ftt.Get("json"))
			mm[ftt.Get("json")] = fv.Int()
		} else if ft.String() == "float32" || ft.String() == "float64" {
			//fmt.Println("    Got float value, tag:", ftt.Get("json"))
			mm[ftt.Get("json")] = fv.Float()
		} else if ft.String() == "bool" {
			//fmt.Println("    Got bool value, tag:", ftt.Get("json"))
			mm[ftt.Get("json")] = fv.Bool()
		} else if ft.String() == "string" {
			//fmt.Println("    Got string value, tag:", ftt.Get("json"))
			mm[ftt.Get("json")] = fv.String()
		} else if ft.String() == "[]int" {
			// @todo: 反射数组成员好像比较复杂，暂且跳过它们。
			fmt.Println("    Got []int value, tag:", ftt.Get("json"))
		} else if ft.String() == "[]float32" {
			fmt.Println("    Got []float32 value, tag:", ftt.Get("json"))
		} else if ft.String() == "[]float64" {
			fmt.Println("    Got []float64 value, tag:", ftt.Get("json"))
		} else if ft.String() == "[]bool" {
			fmt.Println("    Got []bool value, tag:", ftt.Get("json"))
		} else if ft.String() == "[]string" {
			fmt.Println("    Got []string value, tag:", ftt.Get("json"))
		} else if ft.String() == "map[string]string" {
			fmt.Println("    Got map[string]string value, tag:", ftt.Get("json"))
		} else {
			fmt.Println("UNKNOW FMT:", ftt, ",Json tag:", ftt.Get("json"))
		}
	}
	fmt.Println("从反射中重新构建的对象:", mm)

	/*
		bytes, err := json.Marshal(dmJson)
		if err != nil {
			fmt.Println("序列化JSON发生错误:", err.Error())
		} else {
			fmt.Println("序列化为字符串的结果：", string(bytes))
		}
		// 反序列化： 从JSON字符串为结构体赋值。
		tagdmJson2 := &tagdemost{}
		json.Unmarshal(bytes, tagdmJson2)
		fmt.Println("反序列化后:", tagdmJson2)
	*/
}

func main() {
	// 例1 结构体不使用tag时的序列化和反序列化。
	test1()
	fmt.Println("--------------------------")
	// 例2 反射结构体！
	test2()
}
